#include "logmanagement.h"
#include <QSettings>
#include <QCoreApplication>
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>

LogManagement &LogManagement::getInstance()
{
    static LogManagement instance;
    return instance;
}

LogManagement::LogManagement(QObject *parent) : QObject(parent)
{
    dataPtr.reset(new LogManagementPrivate());
    initClient();
    initModels();
}

LogManagement::~LogManagement()
{
    // 先停止定时器防止再触发检查
    if (dataPtr->healthDBTimer && dataPtr->healthDBTimer->isActive())
    {
        dataPtr->healthDBTimer->stop();
    }
    delete dataPtr->operationLogModel;
}

void LogManagement::initClient()
{
    auto create_channel = [](QString ip)
    {
        QString congfig = QString();
#ifdef USE_PACKAGE_ENABLE
        congfig = QCoreApplication::applicationDirPath() + "/config/config.ini";
#else
        congfig = CONFIG_FILE_PATH;
#endif
        QSettings settings(congfig, QSettings::IniFormat);
        auto portIP = settings.value(QString("client/%1").arg(ip)).toString().toStdString();
        grpc::ChannelArguments args;
        args.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, 10000);
        args.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 5000);
        args.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1);
        return grpc::CreateCustomChannel(portIP, grpc::InsecureChannelCredentials(), args);
    };
    auto client = std::make_shared<DBClient>(create_channel("portIPDB"));
    dataPtr->client = std::make_shared<DBClientThreadHandler>(client);

    // 创建健康检查定时器
    dataPtr->healthDBTimer = new QTimer(this);
    connect(dataPtr->healthDBTimer, &QTimer::timeout, this, [this]()
            { checkDatabaseStateAsync(); });
    dataPtr->healthDBTimer->start(3000);
}

void LogManagement::initModels()
{
    dataPtr->operationLogModel = new RemoteTableModel("operationlog", dataPtr->client, this);
    QMap<QString, QString> opMap = {
        {"id", "ID"},
        {"time", "时间"},
        {"content", "内容"},
        {"operation", "操作"}};
    auto opList = QStringList() << "id"
                                << "time"
                                << "content"
                                << "operation";
    dataPtr->operationLogModel->initHeader(opMap, opList);

    QMap<QString, QString> generalMap = {
        {"id", "ID"},
        {"time", "开始时间"},
        {"timeing", "耗时(分钟)"},
        {"content", "钢包号"},
        {"result", "工序结果"},
        {"details", "检测"},
        {"changed", "编辑"},
        {"operation", "删除"}};
    auto generalList = QStringList() << "id"
                                     << "content"
                                     << "result"
                                     << "time"
                                     << "timeing"
                                     << "details"
                                     << "changed"
                                     << "operation";
    dataPtr->DZCSModel = new RemoteTableModel("DZCS", dataPtr->client, this);
    dataPtr->DZCSIMGModel = new RemoteTableModel("DZCS_image", dataPtr->client, this);
    dataPtr->DZCSModel->initHeader(generalMap, generalList);

    dataPtr->YGCZModel = new RemoteTableModel("YGCZ", dataPtr->client, this);
    QMap<QString, QString> YGCZMap = {
        {"id", "ID"},
        {"time", "开始时间"},
        {"timeing", "耗时(分钟)"},
        {"content", "钢包号"},
        {"result", "工序结果"},
        {"changed", "编辑"},
        {"operation", "删除"}};
    auto YGCZList = QStringList() << "id"
                                  << "content"
                                  << "result"
                                  << "time"
                                  << "timeing"
                                  << "changed"
                                  << "operation";
    dataPtr->YGCZModel->initHeader(YGCZMap, YGCZList);

    dataPtr->SKSYModel = new RemoteTableModel("SKSY", dataPtr->client, this);
    dataPtr->SKSYIMGModel = new RemoteTableModel("SKSY_image", dataPtr->client, this);
    dataPtr->SKSYModel->initHeader(generalMap, generalList);

    dataPtr->SKCZModel = new RemoteTableModel("SKCZ", dataPtr->client, this);
    dataPtr->SKCZIMGModel = new RemoteTableModel("SKCZ_image", dataPtr->client, this);
    dataPtr->SKCZModel->initHeader(generalMap, generalList);

    dataPtr->JYLSModel = new RemoteTableModel("JYLS", dataPtr->client, this);
    dataPtr->JYLSIMGModel = new RemoteTableModel("JYLS_image", dataPtr->client, this);

    QMap<QString, QString> JYLSMap = {
        {"id", "ID"},
        {"time", "开始时间"},
        {"timeing", "耗时(分钟)"},
        {"content", "钢包号"},
        {"result", "工序结果"},
        {"weight", "引流砂重量"},
        {"details", "检测"},
        {"changed", "编辑"},
        {"operation", "删除"}};
    auto JYLSList = QStringList() << "id"
                                  << "content"
                                  << "result"
                                  << "time"
                                  << "timeing"
                                  << "weight"
                                  << "details"
                                  << "changed"
                                  << "operation";
    dataPtr->JYLSModel->initHeader(JYLSMap, JYLSList);
    dataPtr->matterModel = new RemoteTableModel("checkDevice", dataPtr->client, this);

    QMap<QString, QString> matterMap = {
        {"id", "ID"},
        {"time", "上次检修"},
        {"timeend", "下次检修"},
        {"content", "检修工位"},
        {"matters", "检修事项"},
        {"measures", "检修措施"},
        {"frequency", "检修频次"},
        {"priority", "优先级"},
        {"status", "状态"},
        {"changed", "编辑"},
        {"operation", "删除"}};
    auto matterList = QStringList() << "id"
                                    << "time"
                                    << "timeend"
                                    << "content"
                                    << "matters"
                                    << "measures"
                                    << "frequency"
                                    << "priority"
                                    << "status"
                                    << "changed"
                                    << "operation";
    dataPtr->matterModel->initHeader(matterMap, matterList);

    dataPtr->eventModel = new RemoteTableModel("event_table", dataPtr->client, this);
    QMap<QString, QString> eventMap = {
        {"id", "ID"},
        {"time", "处理时间"},
        {"title", "设备名称"},
        {"content", "内容"},
        {"image_path", "图片"},
        {"opt_type", "操作选择"},
        {"image_show", "图片"},
        {"operation", "操作"}};
    auto eventList = QStringList() << "id"
                                   << "time"
                                   << "title"
                                   << "content"
                                   << "image_path"
                                   << "opt_type"
                                   << "image_show"
                                   << "operation";
    dataPtr->eventModel->initHeader(eventMap, eventList);

    dataPtr->analyModel = new RemoteTableModel("analyse_table", dataPtr->client, this);
    QMap<QString, QString> analyMap = {
        {"id", "ID"},
        {"content", "钢包号"},
        {"ladle_age", "包龄"},
        {"slide_gate_count", "滑板次数"},
        {"nozzle_count", "水口次数"},
        {"dzcs_result", "底砖吹扫"},
        {"ygcz_result", "油缸拆装"},
        {"sksy_result", "水口烧眼"},
        {"skcz_result", "水口拆装"},
        {"jyls_result", "加引流砂"},
        {"time", "开始时间"},
        {"end_time", "结束时间"},
        {"total_duration", "总耗时(分钟)"},
        {"changed", "编辑"},
        {"operation", "删除"}};
    auto analyList = QStringList() << "id"
                                   << "content"
                                   << "ladle_age"
                                   << "slide_gate_count"
                                   << "nozzle_count"
                                   << "dzcs_result"
                                   << "ygcz_result"
                                   << "sksy_result"
                                   << "skcz_result"
                                   << "jyls_result"
                                   << "time"
                                   << "end_time"
                                   << "total_duration"
                                   << "changed"
                                   << "operation";
    dataPtr->analyModel->initHeader(analyMap, analyList);
}

void LogManagement::handleDBDisconnection()
{
    emit databaseDisconnected();
}

void LogManagement::handleDBReconnection()
{
    emit databaseReconnected();
}

void LogManagement::checkDatabaseStateAsync()
{
    if (!dataPtr->client)
        return;

    // 使用带超时的健康检查
    bool isConnected = false;
    QFuture<bool> future = QtConcurrent::run([&]()
                                             { return dataPtr->client->getClient()->CheckHealth(); });

    // 设置超时时间（2秒）
    QFutureWatcher<bool> watcher;
    QEventLoop loop;
    QTimer timer;
    timer.setSingleShot(true);

    QObject::connect(&watcher, &QFutureWatcher<bool>::finished, &loop, &QEventLoop::quit);
    QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);

    watcher.setFuture(future);
    timer.start(2000); // 2秒超时
    loop.exec();

    if (timer.isActive())
    {
        // 在超时前完成
        isConnected = watcher.result();
    }
    else
    {
        // 超时处理
        watcher.cancel();
        qWarning() << "Database health check timed out";
    }

    // 使用信号通知主线程状态变化
    QMetaObject::invokeMethod(
        this, [this, isConnected]()
        { handleHealthCheckResult(isConnected); },
        Qt::QueuedConnection);
}

void LogManagement::handleHealthCheckResult(bool isConnected)
{
    if (!dataPtr->currentDBState && isConnected)
    {
        handleDBReconnection();
    }
    else if (dataPtr->currentDBState && !isConnected)
    {
        handleDBDisconnection();
    }
    dataPtr->currentDBState = isConnected;
}

RemoteTableModel *LogManagement::getOperationLogModel()
{
    return dataPtr->operationLogModel;
}

RemoteTableModel *LogManagement::getDZCSModel()
{
    return dataPtr->DZCSModel;
}

RemoteTableModel *LogManagement::getDZCSIMGModel()
{
    return dataPtr->DZCSIMGModel;
}

RemoteTableModel *LogManagement::getYGCZModel()
{
    return dataPtr->YGCZModel;
}

RemoteTableModel *LogManagement::getSKSYModel()
{
    return dataPtr->SKSYModel;
}

RemoteTableModel *LogManagement::getSKSYIMGModel()
{
    return dataPtr->SKSYIMGModel;
}

RemoteTableModel *LogManagement::getSKCZModel()
{
    return dataPtr->SKCZModel;
}

RemoteTableModel *LogManagement::getSKCZIMGModel()
{
    return dataPtr->SKCZIMGModel;
}

RemoteTableModel *LogManagement::getJYLSModel()
{
    return dataPtr->JYLSModel;
}

RemoteTableModel *LogManagement::getJYLSIMGModel()
{
    return dataPtr->JYLSIMGModel;
}

RemoteTableModel *LogManagement::getMatterModel()
{
    return dataPtr->matterModel;
}

RemoteTableModel *LogManagement::getEventModel()
{
    return dataPtr->eventModel;
}

RemoteTableModel *LogManagement::getAnalyModel()
{
    return dataPtr->analyModel;
}
